package com.dhl.fin.api.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import com.dhl.fin.api.common.dto.QueryDto;
import com.dhl.fin.api.common.service.CommonService;
import com.dhl.fin.api.common.util.CollectorUtil;
import com.dhl.fin.api.common.util.DateUtil;
import com.dhl.fin.api.common.util.ObjectUtil;
import com.dhl.fin.api.common.util.WebUtil;
import com.dhl.fin.api.domain.BankAccount;
import com.dhl.fin.api.domain.DailyRate;
import com.dhl.fin.api.dto.BankCardDataResponseDTO;
import com.dhl.fin.api.dto.PaySuccessRequestDTO;
import com.dhl.fin.api.enums.BankAccountStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.management.Query;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author CuiJianbo
 * @since 2025/3/16
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class BankAccountService extends CommonService<BankAccount> {

    @Autowired
    private FixDepositService fixDepositService;

    @Autowired
    private DailyRateService dailyRateService;

    @Autowired
    private FamilyConfigService familyConfigService;

    @Autowired
    private LendRecordService lendRecordService;

    public void extendExpireDate(PaySuccessRequestDTO paySuccessRequestDTO) throws Exception {
        List<Long> ids = Arrays.stream(paySuccessRequestDTO.getIds().split(",")).map(Long::parseLong).collect(Collectors.toList());
        for (Long id : ids) {
            BankAccount bankAccount = get(id);
            if (ObjectUtil.isNull(bankAccount.getExpireDate())) {
                DateTime expireDate = cn.hutool.core.date.DateUtil.offset(new Date(), DateField.YEAR, paySuccessRequestDTO.getYears());
                bankAccount.setExpireDate(expireDate);
            } else {
                Date startDate = bankAccount.getExpireDate().compareTo(new Date()) <= 0 ? new Date() : bankAccount.getExpireDate();
                DateTime expireDate = cn.hutool.core.date.DateUtil.offset(startDate, DateField.YEAR, paySuccessRequestDTO.getYears());
                bankAccount.setExpireDate(expireDate);
            }
            updateFieldById(id, "expireDate", DateUtil.getTime(bankAccount.getExpireDate()));
            updateFieldById(id, "status", BankAccountStatusEnum.USED.getCode());
        }
    }

    public Boolean checkWillExpireCard() throws Exception {
        String unicode = WebUtil.getStringParam("unicode");
        BankAccount bankAccount = get(QueryDto.builder()
                .available()
                .addWhere("family_unicode = '" + unicode + "'")
                .addWhere("(DATEDIFF(expire_date,now()) < 30 or status='NOT_ACTIVE')")
                .build());
        return ObjectUtil.notNull(bankAccount);
    }

    public List<BankCardDataResponseDTO> getBankCardData(String unicode) throws Exception {
        List<BankAccount> bankAccounts = select(QueryDto.builder()
                .available()
                .addJoinDomain("family")
                .addOrder("family.birthday")
                .addWhere("family.remove = false")
                .addWhere("family.unicode = '" + unicode + "'")
                .addWhere("family_unicode = '" + unicode + "'")
                .build());

        return bankAccounts.stream()
                .map(p -> {
                    Double total = fixDepositService.getTotalFixDepositMoney(p.getId());
                    Integer totalLendMoney = lendRecordService.getTotalLendMoney(p.getId());

                    BankCardDataResponseDTO bankCardDataResponseDTO = p.changeToBankCardDTO();
                    bankCardDataResponseDTO.setTotalFixMoney(String.format("%,.0f", total));
                    bankCardDataResponseDTO.setTotalLendMoney(String.format("%d.00", totalLendMoney));

                    return bankCardDataResponseDTO;
                }).collect(Collectors.toList());

    }

    /**
     * 计算所有银行卡当日的利息
     */
    public void calculateAllAccountInterest() throws Exception {
        Map<String, String> rateConfigs = familyConfigService.getAllFamilyTimeRateConfigs();
        String date = DateUtil.getTime(DateUtil.getSysDate());

        Boolean isDone = dailyRateService.checkDailyInterestIsDone(date);

        if (isDone) { //已完成，就直接结束
            log.info("{}的日利息已计算，无需再计算", date);
            return;
        }

        List<DailyRate> dailyRates = select(QueryDto.builder()
                .available()
                .addWhere("status = '" + BankAccountStatusEnum.USED.getCode() + "'")
                .build()).stream()
                .map(p -> {
                    String yearRate = rateConfigs.get(p.getFamilyUnicode());
                    Double interestValue = (p.getCurrentBalance() * Double.parseDouble(yearRate) / 100) / 365;
                    DailyRate dailyRate = new DailyRate();
                    dailyRate.setCreateTime(DateUtil.getSysTime());
                    dailyRate.setUpdateTime(DateUtil.getSysTime());
                    dailyRate.setCreateUser("system");
                    dailyRate.setUpdateUser("system");
                    dailyRate.setBankAccount(p);
                    dailyRate.setInterest(interestValue);
                    dailyRate.setYearRate(Double.parseDouble(yearRate) / 100);
                    dailyRate.setDay(DateUtil.getSysDate());
                    dailyRate.setCurrentBalance(p.getCurrentBalance());
                    return dailyRate;
                }).collect(Collectors.toList());

        dailyRateService.batchInsert(dailyRates);

    }


    public void checkBankCardIsExpired() throws Exception {

        QueryDto queryDto = QueryDto.builder()
                .available()
                .addWhere("status = '" + BankAccountStatusEnum.USED.getCode() + "'")
                .addWhere("expire_date < now()")
                .build();

        List<BankAccount> bankAccounts = select(queryDto);

        if (CollectorUtil.isNoTEmpty(bankAccounts)) {

            //TODO 公众号发送通知消息

            BankAccount bankAccount = new BankAccount();
            bankAccount.setStatus(BankAccountStatusEnum.EXPIRED.getCode());
            updateBySelective(bankAccount, queryDto);
        }

    }

    public List<BankAccount> getAllBankAccounts() throws Exception {
        return select(QueryDto.builder()
                .available()
                .addWhere("status = '" + BankAccountStatusEnum.USED.getCode() + "'")
                .build());
    }

    public List<BankAccount> getAllBankAccountsByFamily(String faUnicode) throws Exception {
        return select(QueryDto.builder()
                .available()
                .addWhere("family_unicode = '" + faUnicode + "'")
                .addWhere("status = '" + BankAccountStatusEnum.USED.getCode() + "'")
                .build());
    }

    public Boolean checkIsAllNotActive() throws Exception {
        String faUnicode = WebUtil.getStringParam("faUnicode");
        List<BankAccount> bankAccounts = select(QueryDto.builder()
                .available()
                .addWhere("family_unicode = '" + faUnicode + "'")
                .build());

        if (CollectorUtil.isNoTEmpty(bankAccounts)) {
            long count = bankAccounts.stream().filter(p -> p.getStatus()
                    .equals(BankAccountStatusEnum.NOT_ACTIVE
                            .getCode())
            ).count();

            return bankAccounts.size() == count;

        }

        return false;

    }

}

